package at.fhooe.stefanirndorfer.effects;

import java.nio.IntBuffer;

import org.lwjgl.BufferUtils;
import org.lwjgl.openal.AL;
import org.lwjgl.openal.AL10;
import org.lwjgl.openal.ALC10;
import org.lwjgl.openal.ALCcontext;
import org.lwjgl.openal.ALCdevice;
import org.lwjgl.openal.EFX10;
import org.lwjgl.openal.EFXUtil;

public class EffectUtils {

	 /**
     * Loads OpenAL and makes sure ALC_EXT_EFX is supported.
     */
    public static void setupEfx() throws Exception {
        // Load and create OpenAL
        if (!AL.isCreated()) {
            AL.create();
        }
        // Query for Effect Extension
        if (!ALC10.alcIsExtensionPresent(AL.getDevice(), EFX10.ALC_EXT_EFX_NAME)) {
            throw new Exception("No ALC_EXT_EFX supported by driver.");
        }
        System.out.println("ALC_EXT_EFX found.");
    }

    /**
     * Runs a series of API calls similar to the tutorials in the Effects Extension Guide of the
     * OpenAL SDK. Nothing is played in this method.
     */
    public static void silentTests() throws Exception {
 
    	 final ALCdevice device = AL.getDevice();
    	 
         // Create context (only necessary if LWJGL context isn't sufficient, done as example)
         final IntBuffer contextAttribList = BufferUtils.createIntBuffer(8);
         contextAttribList.put(ALC10.ALC_FREQUENCY);
         contextAttribList.put(44100);
         contextAttribList.put(ALC10.ALC_REFRESH);
         contextAttribList.put(60);
         contextAttribList.put(ALC10.ALC_SYNC);
         contextAttribList.put(ALC10.ALC_FALSE);
         contextAttribList.rewind();
         // ALC_MAX_AUXILIARY_SENDS won't go above compile-time max. Set to compile-time max if
         // greater.
         contextAttribList.put(EFX10.ALC_MAX_AUXILIARY_SENDS);
         contextAttribList.put(2);
         final ALCcontext newContext = ALC10.alcCreateContext(device, contextAttribList);
         if (newContext == null) {
             throw new Exception("Failed to create context.");
         }
         final int contextCurResult = ALC10.alcMakeContextCurrent(newContext);
         if (contextCurResult == ALC10.ALC_FALSE) {
             throw new Exception("Failed to make context current.");
         }
 
        // Query EFX ALC values
        System.out.println("AL_VERSION: " + AL10.alGetString(AL10.AL_VERSION));
        final IntBuffer buff = BufferUtils.createIntBuffer(1);
        ALC10.alcGetInteger(device, EFX10.ALC_EFX_MAJOR_VERSION, buff);
        System.out.println("ALC_EFX_MAJOR_VERSION: " + buff.get(0));
        ALC10.alcGetInteger(device, EFX10.ALC_EFX_MINOR_VERSION, buff);
        System.out.println("ALC_EFX_MINOR_VERSION: " + buff.get(0));
        ALC10.alcGetInteger(device, EFX10.ALC_MAX_AUXILIARY_SENDS, buff);
        final int maxAuxSends = buff.get(0);
        System.out.println("ALC_MAX_AUXILIARY_SENDS: " + maxAuxSends);
    }

    
    /**
     * 
     * @param numEfxSlots
     * @return
     */
	public static int[] createEffectSlots(int numEfxSlots) {
		int numAuxSlots = 0;
		final int[] auxEffectSlots = new int[numEfxSlots];
		
		 AL10.alGetError();
	        for (numAuxSlots = 0; numAuxSlots < numEfxSlots; numAuxSlots++) {
	            auxEffectSlots[numAuxSlots] = EFX10.alGenAuxiliaryEffectSlots();
	            if (AL10.alGetError() != AL10.AL_NO_ERROR) {
	                break;
	            }
	        }
	        
	        //System.out.println("Created " + numAuxSlots + " aux effect slots.");
	 
		
		return auxEffectSlots;
	}

	
	/**
	 * creates numEfx effects
	 * @param numEfx
	 * @return
	 */
	public static int[] createEffects(int numEfx) {
        int numEffects = 0;
        final int[] effects = new int[2];
        for (numEffects = 0; numEffects < 2; numEffects++) {
            effects[numEffects] = EFX10.alGenEffects();
            if (AL10.alGetError() != AL10.AL_NO_ERROR) {
                break;
            }
        }
        //System.out.println("Created " + numEffects + " effects.");
		return effects;
	}
	
	
	 /**
     * Checks OpenAL for every EFX 1.0 effect and filter and prints the result to the console.
     */
    public static void efxUtilTest() throws Exception {
 
        System.out.println();
        System.out.println("Checking supported effects ...");
        if (EFXUtil.isEffectSupported(EFX10.AL_EFFECT_NULL)) {
            System.out.println("AL_EFFECT_NULL is supported.");
        } else {
            System.out.println("AL_EFFECT_NULL is NOT supported.");
        }
        if (EFXUtil.isEffectSupported(EFX10.AL_EFFECT_EAXREVERB)) {
            System.out.println("AL_EFFECT_EAXREVERB is supported.");
        } else {
            System.out.println("AL_EFFECT_EAXREVERB is NOT supported.");
        }
        if (EFXUtil.isEffectSupported(EFX10.AL_EFFECT_REVERB)) {
            System.out.println("AL_EFFECT_REVERB is supported.");
        } else {
            System.out.println("AL_EFFECT_REVERB is NOT supported.");
        }
        if (EFXUtil.isEffectSupported(EFX10.AL_EFFECT_CHORUS)) {
            System.out.println("AL_EFFECT_CHORUS is supported.");
        } else {
            System.out.println("AL_EFFECT_CHORUS is NOT supported.");
        }
        if (EFXUtil.isEffectSupported(EFX10.AL_EFFECT_DISTORTION)) {
            System.out.println("AL_EFFECT_DISTORTION is supported.");
        } else {
            System.out.println("AL_EFFECT_DISTORTION is NOT supported.");
        }
        if (EFXUtil.isEffectSupported(EFX10.AL_EFFECT_ECHO)) {
            System.out.println("AL_EFFECT_ECHO is supported.");
        } else {
            System.out.println("AL_EFFECT_ECHO is NOT supported.");
        }
        if (EFXUtil.isEffectSupported(EFX10.AL_EFFECT_FLANGER)) {
            System.out.println("AL_EFFECT_FLANGER is supported.");
        } else {
            System.out.println("AL_EFFECT_FLANGER is NOT supported.");
        }
        if (EFXUtil.isEffectSupported(EFX10.AL_EFFECT_FREQUENCY_SHIFTER)) {
            System.out.println("AL_EFFECT_FREQUENCY_SHIFTER is supported.");
        } else {
            System.out.println("AL_EFFECT_FREQUENCY_SHIFTER is NOT supported.");
        }
        if (EFXUtil.isEffectSupported(EFX10.AL_EFFECT_VOCAL_MORPHER)) {
            System.out.println("AL_EFFECT_VOCAL_MORPHER is supported.");
        } else {
            System.out.println("AL_EFFECT_VOCAL_MORPHER is NOT supported.");
        }
        if (EFXUtil.isEffectSupported(EFX10.AL_EFFECT_PITCH_SHIFTER)) {
            System.out.println("AL_EFFECT_PITCH_SHIFTER is supported.");
        } else {
            System.out.println("AL_EFFECT_PITCH_SHIFTER is NOT supported.");
        }
        if (EFXUtil.isEffectSupported(EFX10.AL_EFFECT_RING_MODULATOR)) {
            System.out.println("AL_EFFECT_RING_MODULATOR is supported.");
        } else {
            System.out.println("AL_EFFECT_RING_MODULATOR is NOT supported.");
        }
        if (EFXUtil.isEffectSupported(EFX10.AL_EFFECT_AUTOWAH)) {
            System.out.println("AL_EFFECT_AUTOWAH is supported.");
        } else {
            System.out.println("AL_EFFECT_AUTOWAH is NOT supported.");
        }
        if (EFXUtil.isEffectSupported(EFX10.AL_EFFECT_COMPRESSOR)) {
            System.out.println("AL_EFFECT_COMPRESSOR is supported.");
        } else {
            System.out.println("AL_EFFECT_COMPRESSOR is NOT supported.");
        }
        if (EFXUtil.isEffectSupported(EFX10.AL_EFFECT_EQUALIZER)) {
            System.out.println("AL_EFFECT_EQUALIZER is supported.");
        } else {
            System.out.println("AL_EFFECT_EQUALIZER is NOT supported.");
        }
 
        System.out.println();
        System.out.println("Checking supported filters ...");
        if (EFXUtil.isFilterSupported(EFX10.AL_FILTER_NULL)) {
            System.out.println("AL_FILTER_NULL is supported.");
        } else {
            System.out.println("AL_FILTER_NULL is NOT supported.");
        }
        if (EFXUtil.isFilterSupported(EFX10.AL_FILTER_LOWPASS)) {
            System.out.println("AL_FILTER_LOWPASS is supported.");
        } else {
            System.out.println("AL_FILTER_LOWPASS is NOT supported.");
        }
        if (EFXUtil.isFilterSupported(EFX10.AL_FILTER_HIGHPASS)) {
            System.out.println("AL_FILTER_HIGHPASS is supported.");
        } else {
            System.out.println("AL_FILTER_HIGHPASS is NOT supported.");
        }
        if (EFXUtil.isFilterSupported(EFX10.AL_FILTER_BANDPASS)) {
            System.out.println("AL_FILTER_BANDPASS is supported.");
        } else {
            System.out.println("AL_FILTER_BANDPASS is NOT supported.");
        }
        
        // check air absorbtion
        float aaf = EFX10.AL_AIR_ABSORPTION_FACTOR;
        
        System.out.println("default AL_AIR_ABSORBTION_FACTOR is: " + aaf);
       
    }
}
